// 引入axios
import axios from "axios";
import useUserStore from "../store/userStore";
import router from "@/router/index";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import { ElMessage as message, ElNotification as NOT } from "element-plus";
let userStore = useUserStore();
export let baseURL = import.meta.env.config_baseUrl;
// 请求存储 (不使用数组的原因是 自己维护的队列在乎顺序 axios本身维护了一个队列 且map性能比数组好)
let padding: Map<string, any> = new Map();

// 移除请求队列项
function removePadding(requeryUrl: string) {
  if (padding.has(requeryUrl)) {
    padding.delete(requeryUrl);
  }
}

// 清除请求队列
function clearPadding() {
  padding.clear();
}

// 判断是否需要取消请求
function isRequery(requeryUrl: string, cancelFun?: any) {
  if (padding.has(requeryUrl)) {
    // 请求重复时 取消上一次的请求
    padding.get(requeryUrl).abort("取消重复请求");
  }
  // 更新请求队列
  padding.set(requeryUrl, cancelFun);
}

// 创建axios实例
const httpService = axios.create({
  withCredentials: false, // 允许携带cookie
  baseURL: import.meta.env.config_baseUrl,
  timeout: import.meta.env.config_timeOut, // 请求超时时间 - 10s

  //修改请求头信息
  headers: {
    "Content-Type": "application/json;charset=UTF-8",
  },
});

// 请求拦截
httpService.interceptors.request.use((req: objectType<any>) => {
  NProgress.start();
  if (!req.neverCancel) {
    // 不允许重复请求
    let abortController = new AbortController();
    req.signal = abortController.signal;
    isRequery(req.url, abortController);
  }
  // 请求携带token
  let userData: any = userStore.userInfo;
  let token = userData.userToken;
  if (token) {
    req.headers.token = token;
  }
  console.log(req.data);
  req.data.originMode = import.meta.env.config_mode;
  return req;
});

// 拦截
httpService.interceptors.response.use(
  (res: any) => {
    NProgress.done();
    // 请求响应了 不管是成功还是失败 都要将本次请求移除队列
    removePadding(res.config.url);
    // 登陆的API
    let loginUrl = "/note/user-login";
    let header = res.data.header;
    if (res.config.url === loginUrl && header.code === 999) {
      // 将用户信息存储起来
      let userInfo: any = res.data.body;
      userStore.setToken(userInfo);
    }
    // 1008 用户未登录 3003 登陆失效
    if ([1008, 3003].includes(header.code)) {
      NOT({
        title: "系统提示",
        type: "warning",
        message: header.message || "登陆失效、请重新登陆",
      });
      setTimeout(() => {
        // 清除用户信息
        userStore.clearToken();
        router.push({
          path: "/note/login",
        });
      }, 800);
    } else if (header.code === 4004) {
      // 4004 API不存在
      NOT({
        title: "系统提示",
        type: "warning",
        message: header.message || "API不存在或被弃用、请联系管理员",
      });
    } else if (header.code !== 999) {
      NOT({
        title: "系统消息",
        type: "error",
        message: header.message || "未知异常、数据请求失败！",
      });
    }
    return res.data;
  },
  (error: any) => {
    // 响应报错处理
    if (error.code !== "ERR_CANCELED") {
      // 取消请求的报错不需要清空队列
      clearPadding();
    }

    if (error.code === "ECONNABORTED") {
      NOT({
        title: "接口响应超时",
        type: "warning",
        message: error.message || "接口响应超时",
      });
    }

    if (error.code === "ERR_NETWORK") {
      NOT({
        title: "接口响应超时",
        type: "warning",
        message: "接口路径不可达、请检查服务是否正常开启",
      });
    }

    if (error.response) {
      let data = error.response.data;
      switch (error.response.status) {
        case 403:
          NOT.error({ title: "系统提示", message: "拒绝访问", type: "error" });
          break;
        case 404:
          NOT.error({
            title: "系统提示",
            message: "很抱歉，资源未找到",
            type: "error",
          });
          break;
        case 502:
          NOT.error({
            title: "系统提示",
            message: "服务开小差了，请稍后再试",
            type: "error",
          });
          break;
        case 504:
          NOT.error({ title: "系统提示", message: "网络超时", type: "error" });
          break;
        default:
          NOT.error({
            title: "系统提示",
            message: data.message || "未知原因导致异常",
            type: "error",
          });
          break;
      }
    }
    return Promise.reject(error);
  }
);

/*
 *  get请求
 *  url: 接口地址
 *  params: 参数，格式如下
 * */

export const getAction = <T = any>(
  url: string,
  parameter: any = {},
  config: any = {}
): Promise<BaseResponse<T>> => {
  return axios({
    url: url,
    method: "get",
    params: parameter,
    ...config,
  }) as any;
};

/*
 *  post请求
 *  url: 接口地址
 *  parameter: 请求参数
 *  config：请求配置
 */
export const postAction = <T = any>(
  url: string,
  parameter: any = {},
  config: any = {}
): Promise<BaseResponse<T>> => {
  return httpService({
    url,
    method: "post",
    data: parameter,
    ...config,
  }) as any;
};

export default {
  getAction,
  postAction,
  baseURL,
};
